Most MES quality modules were designed around a simple assumption: a person looks at a defective part, picks a reason code from a dropdown, and that code carries the weight of a judgment call. Reason code 214, “surface contamination.” Reason code 87, “dimensional out-of-spec.” Someone decided. That decision then flows downstream into scrap accounting, genealogy records, and the quality-rate term in your OEE calculation, and everyone downstream trusts it because a trained operator made the call.
Now swap the operator for a convolutional neural network running on an edge inspection station, classifying defects at line speed with a confidence score attached. The code still lands in the same MES field. Finance still maps it to the same general ledger scrap account. But the thing generating that code is fundamentally different from the thing the system was designed around, and a lot of plants are only now discovering that the plumbing underneath doesn’t know the difference.
The mapping was never built for this input
Reason-code-to-GL mapping tables in most MES quality modules are static lookup tables: code X always debits scrap account Y, always attributes to defect category Z for Pareto reporting, always decrements good-count in the OEE quality-rate calculation. That’s fine when a human is the classifier, because a human either assigns a code or doesn’t — there’s no in-between state to account for.
AI classifiers don’t work that way. They emit a class and a confidence score, and increasingly a plant runs a threshold below which a part gets flagged for human review rather than auto-classified. That third state — “flagged, pending review, not yet a final defect code” — often doesn’t exist as a legitimate state in the MES workflow. If the integration was done quickly, low-confidence parts either get force-classified into the closest-matching reason code anyway, or they sit in a review queue that isn’t wired into the scrap transaction at all. Either failure mode corrupts the numbers, just in different directions.
Silent misclassification versus silent omission
Force-classifying low-confidence detections inflates specific defect categories with noise. Your Pareto chart for “surface contamination” starts absorbing parts that are actually lighting artifacts on the camera, or fixturing shadows the model was never trained to disambiguate from real defects. Root-cause teams start chasing a contamination problem that’s partly a vision-system tuning problem.
The omission failure is worse because it’s quieter. Parts sitting in a review queue that isn’t transactionally linked to the scrap GL account are physical scrap sitting on a shop floor with no accounting entry behind them yet, or ever, if nobody closes the loop. Finance’s cost-of-quality rollup and the MES yield report start drifting apart, and because both systems look internally consistent, nobody notices until a monthly reconciliation turns up a gap nobody can explain with a normal variance story.
Confidence thresholds are a quality-accounting decision, not just a model-tuning knob
This is the part that tends to get owned by the wrong team. Confidence threshold selection usually happens as a data science and vision-integration exercise — pick the operating point on the ROC curve that balances false accepts against false rejects for the process. That’s a legitimate engineering question, but it is not the same question as: at what confidence level are we willing to let this classification post an automated, unreviewed transaction to a GL scrap account?
Those two thresholds should not automatically be the same number, and in my experience they rarely get discussed as separate decisions. A vision team optimizing for defect-detection accuracy has no particular reason to think about downstream financial materiality. A controller reviewing scrap variances has no visibility into what threshold the model is running at. The reason-code mapping sits exactly in the gap between those two worlds, and right now almost nobody owns that gap explicitly.
What a workable design actually looks like
- Add a real intermediate state. “Auto-classified — high confidence,” “Auto-classified — pending review,” and “Operator-confirmed” should be distinct states in the MES quality transaction, not collapsed into one reason-code field the moment the model fires.
- Set two thresholds, not one. A model-performance threshold for what counts as a usable classification, and a separate, usually higher, accounting threshold for what’s allowed to auto-post to a scrap GL account without human sign-off. Below the accounting threshold, the part is physically segregated and scrapped, but the financial transaction waits for confirmation.
- Version the mapping table. When the classifier model gets retrained or the threshold gets adjusted, the reason-code-to-GL mapping in effect at that time needs to be traceable against the genealogy record. Otherwise your quarter-over-quarter Pareto trends are comparing apples classified by model v3 against oranges classified by model v4, with no way to tell which behavior shift is real and which is an artifact of the model update.
- Reconcile queue depth, not just totals. Track how many parts are sitting in “pending review” at any given time and how long they sit there. A growing, aging review queue is exactly the kind of thing that quietly becomes unaccounted scrap.
The OEE quality-rate term is the other casualty
ISA-95 and classical OEE math treat quality rate as good units over total units, and that ratio assumes every unit has actually been definitively judged. When a meaningful share of production is sitting in an unresolved review state, plants tend to make one of two bad choices by default: count pending-review parts as good (which inflates OEE and hides an emerging defect trend until it’s much worse) or count them as scrap immediately (which understates OEE and can trigger unnecessary line-down investigations for what turns out to be a camera-angle false positive). Neither is defensible once someone asks how the number was actually computed, and “the software just did it that way” is not an answer that survives an audit.
The fix isn’t complicated in concept — carry pending-review units in their own bucket, exclude them from the quality-rate denominator resolution until they’re actually resolved, and report queue-adjusted OEE alongside the standard figure so operations and finance are looking at the same caveat. It is, however, work that has to be deliberately designed into the MES quality module rather than assumed to fall out naturally from turning on an AI inspection feed.
Whose job is this, exactly
The honest answer is that it belongs to a group that doesn’t naturally exist yet in most plants: someone with enough quality-engineering fluency to understand what a confidence score actually means statistically, enough MES configuration authority to touch the reason-code and GL mapping tables, and enough standing with finance to have the cost-of-quality reconciliation conversation before the auditors do. In a lot of organizations that’s currently split three ways across a data science team, an MES administrator, and a controller who’s never seen the model’s confusion matrix. Nobody’s wrong, exactly. Nobody’s covering the seam.
If you’re rolling out AI-based defect classification and haven’t yet had an explicit conversation about where the accounting threshold sits relative to the model’s operating threshold, that conversation is overdue — and it’s a much cheaper conversation to have now than after finance has spent a quarter trying to explain a scrap-cost variance that traces back to a review queue nobody was watching.
This article was written with the assistance of artificial intelligence. While we aim for accuracy, the information may be incomplete, out of date, or incorrect, and should be independently verified before you rely on it for any decision. It is provided for general information only and does not constitute professional advice.
